package boot.spring.config;

import javax.jms.*;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.RedeliveryPolicy;
import org.apache.activemq.broker.region.Subscription;
import org.apache.activemq.broker.region.policy.DeadLetterStrategy;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.apache.activemq.command.Message;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.config.SimpleJmsListenerContainerFactory;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.jms.core.JmsTemplate;

/**
 * sessionAcknowledgeMode 有5种应答模式（JMS标准4种，ActiveMq独有1种）
 * 当设置为 SESSION_TRANSACTED 模式时，JmsListenerContainerFactory bean 设置 .setSessionTransacted(true);
 */
@Configuration
public class ActiveMQConfig {
    // 令牌自定义标识
    @Value("${spring.activemq.user}")
    private String userName;
    @Value("${spring.activemq.password}")
    private String password;
    @Value("${spring.activemq.broker-url}")
    private String brokerUrl;

    @Bean(name = "queue")
    public Queue queue() {
        Queue queue = new ActiveMQQueue("myqueue");
        return queue;
    }

    @Bean(name = "topic")
    public Topic topic() {
        return new ActiveMQTopic("mytopic");
    }

    private final int sessionAcknowledgeMode = Session.SESSION_TRANSACTED;
    /**
     * 获取 activeMQConnectionFactory（connectionFactory）
     * @param redeliveryPolicy
     * @return
     */
    @Bean
    public ActiveMQConnectionFactory activeMQConnectionFactory(RedeliveryPolicy redeliveryPolicy){
        ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(userName, password, brokerUrl);
        factory.setTrustAllPackages(true);
        factory.setRedeliveryPolicy(redeliveryPolicy);
        //是否异步发送消息
        factory.setUseAsyncSend(true);
        return factory;
    }
    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerQueue(ActiveMQConnectionFactory activeMQConnectionFactory){
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        bean.setConnectionFactory(activeMQConnectionFactory);
        //设置连接数
        bean.setConcurrency("1-10");
        //重连间隔时间
        bean.setRecoveryInterval(1000L);
        bean.setSessionAcknowledgeMode(sessionAcknowledgeMode);
        //是否开启带有事务的session 启动报错
        bean.setSessionTransacted(true);
        return bean;
    }
    
    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerTopic(@Qualifier("activeMQConnectionFactory") ActiveMQConnectionFactory activeMQConnectionFactory){
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        //设置为发布订阅方式, 默认情况下使用的生产消费者方式
        bean.setPubSubDomain(true);
        bean.setConnectionFactory(activeMQConnectionFactory);
        return bean;
    }
    /**
     * 优化 消息丢失、生产者发送失败、消费者消费失败问题
     * https://blog.csdn.net/zhaoyachao123/article/details/78365003
     */
    @Bean
    public RedeliveryPolicy redeliveryPolicy(){
        RedeliveryPolicy  redeliveryPolicy=   new RedeliveryPolicy();
        //是否在每次尝试重新发送失败后,增长这个等待时间
        redeliveryPolicy.setUseExponentialBackOff(true);
        //重发次数,默认为6次   这里设置为10次
        redeliveryPolicy.setMaximumRedeliveries(10);
        //重发时间间隔,默认为1秒
        redeliveryPolicy.setInitialRedeliveryDelay(1);
        //第一次失败后重新发送之前等待500毫秒,第二次失败再等待500 * 2毫秒,这里的2就是value
        redeliveryPolicy.setBackOffMultiplier(2);
        //是否避免消息碰撞
        redeliveryPolicy.setUseCollisionAvoidance(false);
        //设置重发最大拖延时间-1 表示没有拖延只有UseExponentialBackOff(true)为true时生效
        redeliveryPolicy.setMaximumRedeliveryDelay(-1);
        return redeliveryPolicy;
    }
    @Bean
    public JmsTemplate jmsTemplate(@Qualifier("activeMQConnectionFactory") ActiveMQConnectionFactory activeMQConnectionFactory, Queue queue){
        JmsTemplate jmsTemplate=new JmsTemplate();
        //进行持久化配置 1表示非持久化，2表示持久化
        jmsTemplate.setDeliveryMode(DeliveryMode.PERSISTENT);
        jmsTemplate.setConnectionFactory(activeMQConnectionFactory);
        //此处可不设置默认，在发送消息时也可设置队列
        jmsTemplate.setDefaultDestination(queue);
        return jmsTemplate;
    }
}
